import {
  addEdge,
  applyEdgeChanges,
  applyNodeChanges,
  Background,
  BaseEdge,
  Controls,
  getBezierPath,
  getSmoothStepPath,
  getStraightPath,
  Handle,
  Position,
  ReactFlow,
  type Connection,
  type Edge,
  type EdgeChange,
  type EdgeProps,
  type Node,
  type NodeChange,
  type NodeProps,
  type NodeTypes
} from "@xyflow/react";
import "@xyflow/react/dist/style.css";
import { memo, useCallback, useState } from "react";

// 自定义节点类型
export type CustomNode = Node<{ label: string }>;

// 自定义节点
const CustomNode = memo((props: NodeProps<CustomNode>) => {
  return (
    <div className="bg-amber-200 p-4 rounded shadow">
      <Handle type="source" position={Position.Bottom} />
      <div className="text-lg font-bold">{props.data.label}</div>
      <Handle type="target" position={Position.Top} />
    </div>
  );
});

const nodeTypes: NodeTypes = {
  customNode: CustomNode
};

// 自定义连接线
const CustomEdge = ({ sourceX, sourceY, targetX, targetY }: EdgeProps) => {
  // 连线的方式有三种
  // 直线(getStraightPath)，曲线(getSmoothStepPath)，贝塞尔曲线(getBezierPath)
  const [edgePath] = getBezierPath({ sourceX, sourceY, targetX, targetY });

  // return <BaseEdge path={edgePath} />;

  return (
    <>
      <path d={edgePath} stroke="red" strokeWidth={3} fill="none" strokeDasharray="5,5" />
    </>
  );
};

const edgeTypes = {
  customEdge: CustomEdge
};

const initialNodes = [
  {
    id: "n1",
    type: "customNode",
    data: { label: "Input Node" },
    position: { x: 250, y: 50 }
  },
  {
    id: "n2",
    type: "customNode",
    data: { label: "Output Node1" },
    position: { x: 100, y: 200 }
  },
  {
    id: "n3",
    type: "customNode",
    data: { label: "Output Node2" },
    position: { x: 300, y: 200 }
  },
  {
    id: "n4",
    type: "customNode",
    data: { label: "Output Node3" },
    position: { x: 500, y: 200 }
  }
];

const initialEdges: Edge[] = [
  { id: "n1-n2", source: "n1", target: "n2", type: "customEdge" },
  { id: "n1-n3", source: "n1", target: "n3", type: "customEdge" },
  { id: "n1-n4", source: "n1", target: "n4", type: "customEdge" }
];

export function DocGraphDemo() {
  const [nodes, setNodes] = useState<Node[]>(initialNodes);
  const [edges, setEdges] = useState<Edge[]>(initialEdges);
  const onNodesChange = useCallback(
    (changes: NodeChange[]) => setNodes(nodesSnapshot => applyNodeChanges(changes, nodesSnapshot)),
    []
  );

  const onEdgesChange = useCallback(
    (changes: EdgeChange[]) => setEdges(edgesSnapshot => applyEdgeChanges(changes, edgesSnapshot)),
    []
  );

  const onConnect = useCallback((params: Connection) => setEdges(edgesSnapshot => addEdge(params, edgesSnapshot)), []);

  return (
    <div className="h-screen w-full">
      <ReactFlow
        nodeTypes={nodeTypes}
        edgeTypes={edgeTypes}
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        onConnect={onConnect}
      >
        <Background />
        <Controls />
      </ReactFlow>
    </div>
  );
}
